import random
import re
from datetime import datetime

from flask import abort,current_app,request, jsonify
from flask import make_response    
from flask import session
from werkzeug.security import generate_password_hash, check_password_hash

from info import constants, db
from info import redis_store
from info.Modules.passport import passport_blu
from info.libs.yuntongxun.sms import CCP
from info.models import User
from info.utils.captcha.captcha.captcha import captcha
from info.utils.response_code import RET

#退出端口接口
@passport_blu.route("/logout")
def logout():
    """
    +    退出登录
    +    核心逻辑：清除session
    +    :return:
    +    """
    session.pop("user_id", None)
    session.pop("mobile", None)
    session.pop("nick_name", None)
    return jsonify(errno=RET.OK, errmsg="退出成功")






#登录的后端接口
@passport_blu.route('/login',methods =['POST'])
def login():
    """
    +    登录功能
    +    1、接收参数 mobile passport
    +    2、校验参数的完整性
    +    3、校验手机号是否符合规则
    +    4、通过手机号是否能查询出该用户
    +    5、如果查询出校验密码是否正确
    +    6、记录用户的登录时间
    +    7、保持登录状态
    +    8、返回响应
    +    :return:
    +    """
    # return jsonify(errno=RET.OK, errmsg='登录成功')

    #1、接收参数 mobile passport
    params_dict = request.json
    mobile = params_dict.get('mobile')
    passport =params_dict.get('passport')
    #2、校验参数的完整性
    if not all([mobile,passport]):
        return jsonify(errno =RET.PARAMERR,errmsg= '参数不全')
    #3、校验手机号是否符合规则
    if not re.match(r'1[35678]\d{9}',mobile):
        return jsonify(errno=RET.PARAMERR,erromsg ='手机号码格式错误')
    #4、通过手机号是否能查询出该用户
    #从redis里通过手机号取出
    try:
        user =User.query.filter_by(mobile =mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库查询错误')
    #判断取出的user是否存在
    if not user:
        return jsonify(errno=RET.NODATA, errmsg='该用户未注册')

    # 6、如果用户存在，校验密码是否正确
    # if user.password != passport:
    if not check_password_hash(user.password_hash, passport):
        return jsonify(errno=RET.PARAMERR, errmsg='密码错误')
    #6、记录用户的登录时间
    user.last_login = datetime.now()
    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库记录错误')
    #7、保持登录状态  mobile 和passport 可以不写，后面通过id就可以查询出用户所有信息返回给前端
    session['mobile'] = mobile
    session['passport'] = passport
    session['user_id'] =user.id
    #8、返回响应
    return jsonify(errno=RET.OK, errmsg='登录成功')





#注册按钮后端接口    为了检验手机短信验证码
@passport_blu.route('/register',methods=["POST"])
def register():
    """
    +    注册功能
    +    1、接收参数 mobile smscode password
    +    2、校验参数的完整性
    +    3、校验手机号是否正确
    +    4、比对数据库中的短信验证码和用户输入的验证码是否一致
    +    5、保存用户信息到mysql数据库
    +    6、保持登录状态  session
    +    7、返回响应
    +    :return:
    +    """
    #1、接收参数 mobile smscode password
    params_dict =request.json
    mobile =params_dict.get('mobile')
    smscode = params_dict.get('smscode')
    password = params_dict.get('password')
    #2、校验参数的完整性
    if not all([mobile,smscode,password]):
        return jsonify(error =RET.PARAMERR,errmsg= '参数不全')
    #3、校验手机号是否正确
    if not re.match(r'1[35678]\d{9}',mobile):
        return jsonify(error=RET.PARAMERR,erromsg ='手机号码格式错误')
    #从数据库里取出真正的短信验证码
    try:
        real_smscode_id =redis_store.get("SMS_" + mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(error=RET.DBERR,erromsg ='数据库查询错误')

    #取出的短信验证码是否过期
    if not real_smscode_id:
        return jsonify(error=RET.NODATA,erromsg ='短信验证码过期')
    # 4、比对数据库中的短信验证码和用户输入的验证码是否一致
    if real_smscode_id != smscode:
        return jsonify(error=RET.DATAERR,erromsg ='短信验证码输入错误')
    #5、保存用户信息到mysql数据库
    user =User()
    user.mobile =mobile
    user.nick_name =mobile
    # user.password_hash =password
    user.password_hash = generate_password_hash(password)
    # user.password = password  和上面是一样的意思
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
    #6、保持登录状态  session
    session['user.id'] = user.mobile
    session['mobile'] = mobile
    session['nick_name'] = user.nick_name
    #7、返回响应
    return jsonify(errno=RET.OK,erromsg ='注册成功')







#图片验证码后端接口   为了生成图片验证码
@passport_blu.route("/image_code")
def get_image_code():
    """
    生成图片验证码
    1、接收uuid
    2、校验uuid是否存在
    3、生成验证码
    4、文本验证码保存到redis数据库中
    5、返回图片验证码
    :return:
    """
#1、接收uuid image_code 那串随机数
    image_code = request.args.get("imageCodeId")
    if not image_code:
        return abort(404)
    #3、生成验证码
    _,text,image = captcha.generate_captcha()
    print(text)
    #4、文本验证码保存到redis数据库中
    try:
        redis_store.setex("ImageCode_"+image_code,constants.IMAGE_CODE_REDIS_EXPIRES,text)
    except Exception as e :
        current_app.logger.error(e)
        return abort(500)
    #5、返回图片验证码
    response = make_response(image)
    response.headers["Content-Type"] = "image/png"

    return response

#发送短信的后端接口   检验图片验证码
@passport_blu.route('/sms_code',methods =['POST'])
def send_sms_code(radis_store=None):
    # 获取短信逻辑
    # 1.获取手机号mobile,用户输入验证码image_code,真实验证码image_code_id
    # 2.检验数据完整性
    # 3.从Radis中取出image_code_id
    # 4.image_code 和image_code_id 对比,失败返回验证码输入错误
    # 5.成功生成随机数(验证码)
    # 5.成功通过云通讯发送验证码
    # 6.返回相应给前端 发送成功 开始倒计时

    # 1.获取手机号mobile,用户输入验证码image_code,真实验证码image_code_id
    # return jsonify(error=RET.OK, erromsg='成功')
    params_dict =request.json
    mobile = params_dict.get('mobile')
    image_code = params_dict.get('image_code')
    image_code_id =params_dict.get('image_code_id')
    # 2.检验数据完整性
    if not all([mobile,image_code,image_code_id]):
        return jsonify(error=RET.PARAMERR,erromsg ='参数不全')
    #检验手机号是否符合正则
    if not re.match(r'1[35678]\d{9}',mobile):
        return jsonify(error=RET.PARAMERR,erromsg ='手机号码格式错误')
    # 3.从Radis中取出image_code_id
    try:
        real_image_code =redis_store.get('ImageCode_'+image_code_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(error=RET.DATAERR,erromsg ='数据库查询错误')
    #查看取出的验证码是否过期
    if not real_image_code:
        return jsonify(error=RET.NODATA,erromsg ='验证码过期')
    # 4.image_code 和image_code_id 对比,失败返回验证码输入错误
    if image_code.upper() != real_image_code.upper():
        return jsonify(error=RET.PARAMERR,erromsg ='验证码输入错误')
    # 5.成功生成随机数(验证码)
    sms_code ='%06d' %random.randint(0,999999)
    current_app.logger.info('手机验证码是：%s' % sms_code)
    # 5.成功通过云通讯发送验证码
    # result = CCP().send_template_sms(mobile, [sms_code, 5], 1)
    #在控制台输出短信验证码
    # current_app.logger.info("手机验证码是：%s" % sms_code)
    print(sms_code)

    # 6.返回相应给前端 发送成功 开始倒计时
    #把短信验证码sms_code保存到数据库中
    try:
        redis_store.setex("SMS_" + mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
    except Exception as e:
        return jsonify(error=RET.DBERR,erromsg ='数据库保存失败')

    return jsonify(error=RET.OK,erromsg ='成功')